package com.zzjson.redis;

import com.zzjson.common.utils.PropertiesUtils;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.Pipeline;

import java.util.Collections;
import java.util.List;
import java.util.Properties;

/**
 * <p>****************************************************************************</p>
 * <li>Description : redis单机 </li>
 * <li>Version     : 1.0.0</li>
 * <li>Creation    : 2021年03月02日</li>
 * <li>@author     : zzy0_0</li>
 * </ul>
 * <p>****************************************************************************</p>
 */
public class JedisSingleExample {

	public static void main(String[] args) {
		Properties redisProperties = PropertiesUtils.loadProperties("redis");

		JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
		jedisPoolConfig.setMaxTotal(20);
		jedisPoolConfig.setMaxIdle(10);
		jedisPoolConfig.setMinIdle(5);

		// timeout，这里既是连接超时又是读写超时，从Jedis 2.8开始有区分connectionTimeout和soTimeout的构造函数
		JedisPool jedisPool = new JedisPool(jedisPoolConfig, redisProperties.getProperty("redis.host"), Integer.parseInt(redisProperties.getProperty("redis.port")), 3000, null);

		try (Jedis jedis = jedisPool.getResource()) {
			//从redis连接池里拿出一个连接执行命令

			//******* jedis普通操作示例 ********
			//normalOperation(jedis);

			//******* 管道示例 出错了记得处理对应错误的记录********
			//pipelineOperation(jedis);

			//******* lua脚本示例 ********
			//模拟一个商品减库存的原子操作
			//lua脚本命令执行方式：redis-cli --eval /tmp/test.lua , 10
			luaOperation(jedis);

		} catch (Exception e) {
			e.printStackTrace();
		}
		//注意这里不是关闭连接，在JedisPool模式下，Jedis会被归还给资源池。
	}

	private static void luaOperation(Jedis jedis) {
		jedis.set("product_stock_10016", "15");  //初始化商品10016的库存
		String script = " local count = redis.call('get', KEYS[1]) " +
				" local a = tonumber(count) " +
				" local b = tonumber(ARGV[1]) " +
				" if a >= b then " +
				"   redis.call('set', KEYS[1], a-b) " +
				//模拟语法报错回滚操作
				//" local  bb = 0 " +
				"   bb = 0 " +
				"   return 1 " +
				" end " +
				" return 0 ";
		Object obj = jedis.eval(script, Collections.singletonList("product_stock_10016"), Collections.singletonList("10"));
		System.out.println(obj);
	}


	private static void pipelineOperation(Jedis jedis) {
		//管道的命令执行方式：cat redis.txt | redis-cli -h 127.0.0.1 -a password - p 6379 --pipe
		Pipeline pl = jedis.pipelined();
		for (int i = 0; i < 10; i++) {
			pl.incr("pipelineKey");
			pl.set("zzjson" + i, "zzjson");
			//模拟管道报错 offset -1 是错误的，所以会报错
			pl.setbit("zzjson", -1, true);
		}
		List<Object> results = pl.syncAndReturnAll();
		System.out.println(results);
	}

	private static void normalOperation(Jedis jedis) {
		System.out.println(jedis.set("single1", "zzjson"));
		System.out.println(jedis.get("single1"));
	}
}